import sys

sys.path.append("../lib")
from spread_sheet import Spreadsheet

from inner_util import get_files
from openpyxl.utils import cell
import datetime
from rich import print as rprint
from functools import reduce


TEMPLATE_DIR = "tem"


class SheetTask:
    """
    处理表格任务的类，类包含一个xlsx表文件和对应的配置参数。
    包括两个功能，一是生成模板，二是合并数据

    """

    def __init__(self, config):
        # 配置参数
        # 参数格式如下：
        # {
        #     "name": "能源工业停建缓建",
        #     "area": "A5:O16",
        #     "template": "附件2：2024年来历能源工业停建缓建相关项目清单.xlsx",
        #     "mod_cells": {
        #         "F1": f"表中数据为上月，请更新为{month}月数据",
        #     },
        #     "post_mod_cells": {"A3": f"日期：{timestamp}"},
        # }
        #
        # template 既用做模板，也用做目标
        #

        self.config = config
        self.spread_sheet = Spreadsheet(f"{TEMPLATE_DIR}/{self.config['template']}")

        rprint("处理", self.config)

    def get_default_style(self):
        """
        取得area区域第一个单元格的样式，需要默认的font, fill

        此函数获取指定区域（由self.config['area']定义）中第一个单元格的样式，并返回包含字体和填充样式的字典。

        返回:
            dict: 包含默认字体和填充样式的字典。
        """
        first_cell_coord = self.spread_sheet.ws[self.config["area"]][0][0].coordinate
        return self.spread_sheet.get_cell_style(first_cell_coord)

    def get_mod_style(self, src_style):
        """
        获取修改后的样式。

        此函数接收一个源样式字典，并返回一个新的样式字典，其中字体颜色为红色，字体加粗，填充颜色为黄色。

        参数:
            src_style (dict): 源样式字典，包含字体和填充样式。

        返回:
            dict: 修改后的样式字典，包含新的字体和填充样式。
        """
        new_font = src_style["font"]
        new_fill = src_style["fill"]

        new_font.color = "FF0000"
        new_font.bold = True

        new_fill.start_color = "FFFF00"
        new_fill.end_color = "FFFF00"
        return {"font": new_font, "fill": new_fill}

    def build_tempalte(self, month, target_dir, with_style=False):
        """
        构建模板文件。

        此函数根据给定的月份和目标目录构建一个模板文件。模板文件是基于原始电子表格文件生成的，其中数据区域的样式被设置为默认样式，并且根据配置修改特定单元格的内容。

        参数:
            month (str): 月份，用于生成模板文件名。
            target_dir (str): 目标目录，模板文件将保存到该目录。
            with_style (bool, optional): 是否应用默认样式到修改的单元格。默认为False。

        返回:
            None
        """
        # 修改数据区域样式为默认
        default_style = self.get_default_style()

        self.spread_sheet.set_range_style(
            self.config["area"],
            font=default_style["font"],
            fill=default_style["fill"],
        )

        # 修改内容的格子
        mod_cells = self.config["mod_cells"]

        for k, v in mod_cells.items():
            print(f"Modify {k} -> {v}")
            self.spread_sheet.set_cell_value(k, v)
            if with_style:
                self.spread_sheet.set_cell_style(k, default_style)

        timestamp = datetime.date.today().strftime("%Y%m%d")
        self.spread_sheet.save_as(
            f"{target_dir}/{timestamp}-模板-{month}月-{self.config['template']}"
        )

    def recive_data(self, data_dir, target_dir):
        """
        接收数据并处理。

        此函数从指定的数据目录中获取所有Excel文件，比较每个文件与原始电子表格文件在指定区域内的差异，
        标记并突出显示差异单元格，然后将处理后的结果保存到目标目录。

        参数:
            data_dir (str): 数据目录，包含要处理的Excel文件。
            target_dir (str): 目标目录，处理后的文件将保存到该目录。

        返回:
            str: 处理后的文件路径。
        """
        # 获取数据目录下所有的Excel文件
        files = []
        try:
            files = get_files(data_dir, exts=[".xlsx"])
            if len(files) == 0:
                print("No files found")
        except FileNotFoundError as err:
            print(err)
        # 如果没有找到文件，则打印提示信息并返回

        # return None

        # 获取默认样式和修改后的样式
        default_style = self.get_default_style()
        mod_style = self.get_mod_style(default_style)

        for f in files:
            print("----------------------------")
            right_file = Spreadsheet(f)
            # 获取当前文件与原表在指定区域内的差异单元格
            diff_cells = self.spread_sheet.diff(right_file, self.config["area"])
            # 获取差异单元格的行号
            row_nums = [cell.coordinate_from_string(x)[1] for x in diff_cells]

            # 获取需要修改的行号
            mod_row_index = list(set(row_nums))

            # 如果有需要修改的行，则打印行号
            if len(mod_row_index) > 0:
                keys = [
                    self.spread_sheet.ws.cell(
                        row=row, column=self.config["primary_col"] + 1
                    ).value
                    for row in mod_row_index
                ]
                print(f"数据表 {f} 和原表的差异")
                print(
                    "修改行",
                    list(zip(mod_row_index, keys)),
                )

            # 遍历差异单元格，设置单元格样式
            for diff_cell in diff_cells:
                self.spread_sheet.set_cell_style(
                    diff_cell, mod_style["font"], mod_style["fill"]
                )

        print(f"数据表共{len(files)}张")
        # 获取当前日期
        timestamp = datetime.date.today().strftime("%Y%m%d")

        # 获取需要修改的单元格
        post_mod_cells = (
            self.config["post_mod_cells"] if "post_mod_cells" in self.config else {}
        )

        # 遍历需要修改的单元格，设置单元格值
        for k, v in post_mod_cells.items():
            print(f"Modify {k} -> {v}")
            self.spread_sheet.set_cell_value(k, v)

        # 获取模板文件名
        template = self.config["template"]

        # 构建目标文件名
        target_file = f"{target_dir}/{timestamp}-汇总-{template}"
        # 保存处理后的文件
        self.spread_sheet.save_as(target_file)

        # 返回目标文件路径
        return target_file

    def stat(self, file_path):
        print("-------------------------")
        main_file = Spreadsheet(file_path)

        if self.config["name"] == "未开工":
            b = [x.value for x in main_file.ws["Z"]]
            print("总个数", main_file.ws["A7"].value)
            print("已开工数", b.count("是"))

        elif self.config["name"] == "已开工未入库":
            print("总个数", main_file.ws["A7"].value)
            b = [x.value for x in main_file.ws["AA"]]
            print("已入库数", b.count("是"))

        elif self.config["name"] == "投资完成滞后":
            print("总个数", main_file.ws["A7"].value)
            invs = [x.value for x in main_file.ws["AC"]]
            total = reduce(lambda cur, acc: cur + acc, invs[7:], 0)
            total = int(round(total, 0))

            last_total = 0
            try:
                with open("last", "r") as f:
                    content = f.read()
                    print("read", content)
                    last = content.strip().split("\n")[-1]
                    print("last", last)
                    last_total = int(last)
            except ValueError:
                last_total = 0

            with open("last", "a+") as f:
                f.write(f"{str(total)}\n")

            plus_total = total - last_total
            print(f"经过努力新增完成投资{total}万元，较上周增加{plus_total}万元")
            print(
                "上周投资",
                last_total,
            )
